<?php
/* one to many*/

/*
require_once('CommonUtil.php');
require_once('DBI.class.php');
require_once('dbUtil.php');
*/

/* Example:
 * $otm = new OTM();
 * # one 'news' has many 'category', the one to many relation is stored in 'news_otm_category'
 * 
 * $otm->set_param(array('table'=> 'news', 'key'=>'id', 'value'=>'category'), 
 *                 array('table'=> 'news_otm_category', 'key'=>'oid', 'value' => 'category'));
 * $otm->update($id);
 * tag is kind of otm, but its input is string, it first match with tag table and convert to 
 */



class CMS_OTM{
	protected $key_fieldname;
	protected $value_fieldname;
	protected $table;
	protected $otm_table;
	protected $otm_key_fieldname;
	protected $otm_value_fieldname;
	private   $delim = ',';
	
	protected $tag_table;
	protected $tag_key_fieldname;
	protected $tag_value_fieldname;
	private   $dbh_r=null;
	private   $dbh_w=null;
	
	function __construct(){
	}
	
	function set_param($main_table, $otm_table){
		$this->set_main_table_param($main_table);
		$this->set_otm_table_param($otm_table);
	}
	
	function set_main_table_param($h_param=array()){
	  $this->table           = get_hash_param($h_param, 'table', '');
	  $this->key_fieldname   = get_hash_param($h_param, 'key',   'id');
	  $this->value_fieldname = get_hash_param($h_param, 'value', 'category');
	}
	
	function set_otm_table_param($h_param=array()){
	  $this->otm_table           = get_hash_param($h_param, 'table', '');
	  $this->otm_key_fieldname   = get_hash_param($h_param, 'key',   'oid');
	  $this->otm_value_fieldname = get_hash_param($h_param, 'value', 'category');
	}
	
	
	function set_tag_table_param($h_param=array()){
	  $this->tag_table           = get_hash_param($h_param, 'table', '');
	  $this->tag_key_fieldname   = get_hash_param($h_param, 'key',   'id');
	  $this->tag_value_fieldname = get_hash_param($h_param, 'value', 'name');
	}
	
	function tag_to_id($string){
		$dbh_r = $this->db_connect('read');

  	$a_string = explode($this->delim, $string);
    $a_result = array();
    foreach ($a_string as $string){
    	$tag_id = db_select_one($dbh_r, 'select '.
	      $this->tag_key_fieldname.' from '.$this->tag_table.' where '.
	      $this->tag_value_fieldname.'=?', $string);
	    
	    if ($tag_id > 0){
	    	# 
	    } else {
		    $dbh_w = $this->db_connect('write');
	      db_do($dbh_w, 'insert into '.$this->tag_table.' ( '.$this->tag_value_fieldname.' ) '.
	        ' values (?)', $string);
	      $tag_id = db_last_insert_id($dbh_w);  	
	    }
      array_push($a_result, $tag_id);	
    }
 
 
    $temp = implode($this->delim, $a_result);
    #echo "tag_to_id $string => $temp\n";
    return $temp;
	}
	
	
	function db_connect($mode='read'){
		if ($mode == 'write'){
			if ($this->dbh_w == null){
		    $db = new DBI('write');
        $this->dbh_w = $db->connect();   
      }
      return $this->dbh_w;
		}
		
		if ($this->dbh_r == null){
		  $db = new DBI('read');
      $this->dbh_r = $db->connect();   
    }
    return $this->dbh_r;
	} 
	
	function mdel($a_key){
		if (count($a_key) > 0 ){
			$dbh_w = $this->db_connect('write');
      $key = implode($this->delim, $key);
      db_do($dbh_w, 'delete from '.$this->otm_table.' where '.$this->otm_key_fieldname." in ($key)");
    }
  }
	
	
	function del($key){
		$dbh_w = $this->db_connect('write');
    db_do($dbh_w, 'delete from '.$this->otm_table.' where '.$this->otm_key_fieldname.'=?',  $key);
	}
	
	function mupdate($a_key){
		if (count($a_key) > 0 ){
			foreach ($a_key as $key){
				$this->update($key);
		  }
		}
	}
	
	function update_by_key_value($key, $value){
	  $dbh_r = $this->db_connect('read');
    $a_value = explode($this->delim, $value);
    $h_value = array_fill_keys($a_value, 1); # convert array to hash, use a_value as key, 1 as value
    
    #echo "Original : Key: $key, Value: Value\n";
    # get original mapping
	  $a_otm_value = db_selectcol_array($dbh_r, 'select '.
	  $this->otm_value_fieldname.' from '.$this->otm_table.' where '.
	  $this->otm_key_fieldname.'=?', $key);
  
    $a_remove = array();
    # ignore mapping already exists in otm_mapping_table  table
	  foreach ($a_otm_value as $otm_value){
		  if (isset($h_value[$otm_value])){ # it is already exists in otm_mapping_table
			  unset($h_value[$otm_value]);  # no need to update it
	    } else {
	  	  array_push($a_remove, $otm_value);
      }	  
    }	
  
	  $dbh_w = $this->db_connect('write');
    # batch delete
    if (count($a_remove)  > 0){
      $remove = implode($this->delim, $a_remove);
      db_do($dbh_w, 'delete from '.$this->otm_table.' where '.$this->otm_key_fieldname.'=? and '.$this->otm_value_fieldname." in ($remove)",  $key);
    }
  
    # up to here all original '$fieldname' in mapping table has processed.
	  # adding new '$fieldname'
	  foreach ($h_value as $temp_key => $dummy_value ){
	    db_do($dbh_w, 'insert into '.$this->otm_table.' ('.$this->otm_key_fieldname.', '.$this->otm_value_fieldname.') values (?,?)', array($key, $temp_key));
    }	


	}
	
	function update($key){
	  
	  $dbh_r = $this->db_connect('read');
    
    $value = db_select_one($dbh_r, 'select '.$this->value_fieldname.' from '.$this->table.' where '.$this->key_fieldname.'=?', $key);
    return $this->update_by_key_value($key, $value);
  }
  
  
} # end class
?>